﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Hands.Queue;
using System.Threading;
using System.Reflection;

namespace Hands.EventBus
{
    public sealed class EventCenter : IPublish, IHandlerRegistration
    {
        private readonly Dictionary<Type, Handler> handlerList = new Dictionary<Type, Handler>();

        private readonly ConcurrentLinkedQueue<Event> queue = new ConcurrentLinkedQueue<Event>();

        public EventCenter()
        { }

        /*当一个线程到达后，会先执行A步骤，将数据放入队列中，A执行完成后，线程可能会用完时间片而挂起，则其他线程执行A步骤
         *当线程再次执行时，会执行B步骤，将队列首部的消息发送出去。
         */
        public void publish(Event eventMessage)
        {
            queue.put(eventMessage); /*A*/
            /*B*/
            if (!queue.IsEmpty)
            {
                Event message = queue.get();
                if (handlerList.ContainsKey(message.EventType))
                {
                    handlerList[message.EventType].Invoke(message);
                }
            }
        }

        public void register(Type messageType, Handler handler)
        {
            registerHandler(messageType, handler);
        }

        public void register(HashSet<Type> messageTypes, Handler handler)
        {
            foreach (Type messageType in messageTypes)
            {
                registerHandler(messageType, handler);
            }
        }

        private void registerHandler(Type messageType, Handler handler)
        {
            if (!handlerList.ContainsKey(messageType))
            {
                handlerList.Add(messageType, handler);
            }
            else
            {
                throw new HandlerRegistedException(messageType.ToString());
            }
        }
    }
}
